package com.mobimagic.lockscreen.remaintime;

import java.util.ArrayList;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;

import com.mobimagic.lockscreen.AppEnv;
import com.mobimagic.lockscreen.MobileChargingHelper;
import com.mobimagic.lockscreen.remaintime.StaticHandler.MessageHandler;
import com.mobimagic.lockscreen.remaintime.aidl.ChargingData;
import com.mobimagic.lockscreen.remaintime.aidl.ChargingDatas;
import com.mobimagic.lockscreen.remaintime.aidl.ChargingServiceAidl;
import com.mobimagic.lockscreen.remaintime.aidl.RemaintTimeWatcher;
import com.qihoo360.mobilesafe.lib.appmgr.util.ThreadPoolUtils;

public class MobileChargingService extends Service implements MessageHandler {

    public static final boolean DEBUG = AppEnv.bAppdebug;

    public static final String TAG = "MobileChargingService";
    public static final String INTENT_ACTION = "intent_action";
    public static final long STOPSELF_WHEN_DISCONNECT_DELAY_TIME = 3000 * 60;
    public static final int MSG_REGIST = 0;
    public static final int MSG_UNREGIST = 1;
    public static final int MSG_UPDATE_REMAINT_TIME = 2;
    public static final int MSG_GET_DATA = 3;
    public static final int MSG_CONNECT = 4;
    public static final int MSG_SAVE = 5;
    public static final int MSG_SECURITY_SERVICE_CREATE = 6;
    public static final int MSG_STOPSELF_WHEN_DISCONNECT = 7;
    private boolean needHandleConnectWhenGet = false;

    /**
     * 充电线连接上，和上次充电结束的时间相差3分钟以内，数据有效
     */
    private static final int CONNECT_OVER_DUE = 3 * 60 * 1000;
    private ChargingDatas mChargingDatas = null;
    RemoteCallbackList<RemaintTimeWatcher> remoteCallbackList;
    BroadcastReceiver batteryChangedReceiver;
    Handler handler;
    private ChargingServiceAidl chargingServiceAidl = new ChargingServiceAidl.Stub() {

        @Override
        public void unRegister(RemaintTimeWatcher remaintTimeWatcher) throws RemoteException {
            handler.sendMessage(handler.obtainMessage(MSG_UNREGIST, remaintTimeWatcher));
            if (DEBUG) {
                Log.d(TAG, "unRegister");
            }
        }

        @Override
        public void register(RemaintTimeWatcher remaintTimeWatcher) throws RemoteException {
            handler.sendMessage(handler.obtainMessage(MSG_REGIST, remaintTimeWatcher));
            if (DEBUG) {
                Log.d(TAG, "register");
            }

        }

        @Override
        public ChargingDatas getChargingDatas() throws RemoteException {
            return mChargingDatas;
        }

        @Override
        public void calc(int i) throws RemoteException {
            ChargingUtils.reCalcRemindTime(mChargingDatas, CalcSlopeStrategy.getInstance(i));
            notifyRemaindTime();
            saveAsync(mChargingDatas, false);
        }

        @Override
        public int getRemaintTime() throws RemoteException {
            return getRemainderTime();
        }
    };;

    @Override
    public void onCreate() {
        super.onCreate();
        if (DEBUG) {
            Log.d(TAG, "Service onCraete()");
        }
        handler = new StaticHandler(this, Looper.getMainLooper());
        remoteCallbackList = new RemoteCallbackList<RemaintTimeWatcher>();
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                synchronized (MobileChargingService.this) {
                    ChargingDatas chargingDatas = null;
                    try {
                        if (DEBUG) {
                            Log.d(TAG, "Service onCraete() fromJson begin");
                        }
                        chargingDatas = ChargingUtils.fromJson(getApplicationContext());
                        if (DEBUG) {
                            Log.d(TAG, "Service onCraete() fromJson end chargingDatas=" + chargingDatas);
                        }
                    } catch (Exception e) {
                        if (DEBUG) {
                            Log.e(TAG, "Service onCraete() fromJson exception", e);
                        }
                        chargingDatas = null;
                        try {
                            ChargingUtils.save(MobileChargingService.this, null);
                        } catch (Exception e1) {
                        }
                    }
                    if (chargingDatas == null) {
                        if (DEBUG) {
                            Log.d(TAG, "Service onCraete() new ChargingDatas");
                        }
                        chargingDatas = new ChargingDatas();
                    }
                    handler.sendMessage(handler.obtainMessage(MSG_GET_DATA, chargingDatas));
                }
            }
        };
        ThreadPoolUtils.getInstance().execute(runnable);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        intentFilter.addAction(Intent.ACTION_DATE_CHANGED);
        batteryChangedReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                Bundle bundle = intent.getExtras();
                onBatteryChanged(bundle);

            }
        };
        registerReceiver(batteryChangedReceiver, intentFilter);

    }

    public void handleMessage(Message msg) {
        int what = msg.what;

        if (DEBUG) {
            Log.d(TAG, "handleMessage().what=" + what);
        }
        switch (what) {
        case MSG_GET_DATA:
            mChargingDatas = (ChargingDatas) msg.obj;
            if (needHandleConnectWhenGet) {
                handleConnect();
            }
            break;
        case MSG_SECURITY_SERVICE_CREATE:
        case MSG_CONNECT:
            handleConnect();
            break;
        case MSG_SAVE: {
            boolean needStopSelf = (Boolean) msg.obj;
            if (needStopSelf) {
                stopSelf();
            }
            break;
        }
        case MSG_REGIST: {
            RemaintTimeWatcher remaintTimeWatcher = (RemaintTimeWatcher) msg.obj;
            remoteCallbackList.register(remaintTimeWatcher);
            break;
        }
        case MSG_UNREGIST: {
            RemaintTimeWatcher remaintTimeWatcher = (RemaintTimeWatcher) msg.obj;
            remoteCallbackList.unregister(remaintTimeWatcher);
            break;
        }
        case MSG_UPDATE_REMAINT_TIME: {
            int count = remoteCallbackList.beginBroadcast();
            int time = (Integer) msg.obj;
            for (int i = 0; i < count; i++) {
                RemaintTimeWatcher remaintTimeWatcher = remoteCallbackList.getBroadcastItem(i);
                try {
                    remaintTimeWatcher.onRemaintTimeChanged(time);
                } catch (RemoteException e) {
                }

            }
            remoteCallbackList.finishBroadcast();
            break;
        }
        case MSG_STOPSELF_WHEN_DISCONNECT: {
            stopSelf();
            break;

        }

        default:
            break;
        }

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (DEBUG) {
            Log.d(TAG, "Service onStartCommand()");
        }
        parseIntent(intent);

        return START_NOT_STICKY;
    }

    private void parseIntent(Intent intent) {
        if (intent == null) {
            return;
        } else {
            Bundle bundle = intent.getExtras();
            if (bundle == null) {
                return;
            }
            String action = bundle.getString(INTENT_ACTION);
            if (DEBUG) {
                Log.d(TAG, action);
            }
            if (MobileChargingHelper.SECURITY_SERVICE_CREATE.equals(action)) {
                //进程重启
                handler.sendEmptyMessage(MSG_SECURITY_SERVICE_CREATE);
            }
            if (Intent.ACTION_POWER_CONNECTED.equals(action)) {
                handler.sendEmptyMessage(MSG_CONNECT);
            } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
                onBatteryChanged(bundle);

            } else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
                onDisconnect();
                stopSelf();
            }

        }
    }

    private void onBatteryChanged(Bundle bundle) {
        if (mChargingDatas == null) {
            if (DEBUG) {
                Log.d(TAG, "onBatteryChanged  mChargingDatas == null");
            }

            return;
        }
        boolean suc = ChargingUtils.onBatteryChange(mChargingDatas, bundle);
        if (suc) {
            if (DEBUG) {
                Log.d(TAG, "电量有变化");
            }
            saveAsync(mChargingDatas, false);
            notifyRemaindTime();
            checkStopIfNotCharging();
        }
    }

    /**
     * 连续的3个点没充电就stopSelf;
     */
    private void checkStopIfNotCharging() {
        if (DEBUG) {
            Log.d(TAG, "checkStopIfNotCharging.checkStopIfNotCharging mChargingDatas=" + mChargingDatas);
        }

        if (mChargingDatas == null) {
            return;
        }
        int size = mChargingDatas.chargingDatas.size();

        if (size <= 1) {
            return;
        }
        boolean isCharging = mChargingDatas.chargingDatas.get(size - 1).isCharging();
        if (isCharging) {
            return;
        }
        isCharging = mChargingDatas.chargingDatas.get(size - 2).isCharging();
        if (isCharging) {
            return;
        }

        if (DEBUG) {
            Log.d(TAG, "checkStopIfNotCharging 两次都是没充电，结束充电！");
        }
        saveAsync(null, true);
    }

    private int getRemainderTime() {
        if (mChargingDatas == null) {
            return -1;
        }
        ArrayList<ChargingData> list = mChargingDatas.chargingDatas;
        int size = list.size();
        if (size > 0) {
            int reminder = list.get(list.size() - 1).getRemainder();
            return reminder;
        } else {
            return -1;
        }
    }

    private void notifyRemaindTime() {
        handler.sendMessage(handler.obtainMessage(MSG_UPDATE_REMAINT_TIME, getRemainderTime()));
    }

    @Override
    public IBinder onBind(Intent intent) {
        return chargingServiceAidl.asBinder();
    }

    public void end() {

    }

    public void handleConnect() {
        if (DEBUG) {
            Log.i(TAG, "handleConnect() mChargingDatas=" + mChargingDatas);
        }
        if (handler.hasMessages(MSG_STOPSELF_WHEN_DISCONNECT)) {
            handler.removeMessages(MSG_STOPSELF_WHEN_DISCONNECT);
        }
        if (mChargingDatas == null) {
            needHandleConnectWhenGet = true;
            if (DEBUG) {
                Log.d(TAG, "handleConnect() needHandleConnectWhenGet=" + needHandleConnectWhenGet);
            }
            return;
        }
        needHandleConnectWhenGet = false;
        long currentTime = System.currentTimeMillis();
        boolean overDue = mChargingDatas.endTime > 0 && mChargingDatas.endTime + CONNECT_OVER_DUE < currentTime;
        if (DEBUG) {
            Log.d(TAG, "handleConnect() overDue=" + overDue);
        }
        //过期判断
        if (overDue) {
            mChargingDatas.startTime = System.currentTimeMillis();
            mChargingDatas.lastBattery = -2;
            mChargingDatas.chargingDatas.clear();
            saveAsync(mChargingDatas, false);
            IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
            Intent intent = registerReceiver(null, ifilter);
            boolean suc = ChargingUtils.onBatteryChange(mChargingDatas, intent);
            if (DEBUG) {
                Log.d(TAG, "handleConnect() onBatteryChange suc=" + suc);
            }
            if (suc) {
                if (DEBUG) {
                    Log.d(TAG, "handleConnect() saveAsync");
                }
                saveAsync(mChargingDatas, false);
                if (DEBUG) {
                    Log.d(TAG, "handleConnect() notifyRemaindTime");
                }
                notifyRemaindTime();
            }
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        if (DEBUG) {
            Log.d(TAG, "onUnbind");
        }
        return super.onUnbind(intent);
    }

    public void onDisconnect() {
        if (DEBUG) {
            Log.d(TAG, "充电结束");
        }
        if (mChargingDatas != null) {
            mChargingDatas.endTime = System.currentTimeMillis();
            saveAsync(mChargingDatas, true);
        }
        handler.removeMessages(MSG_STOPSELF_WHEN_DISCONNECT);
        handler.sendEmptyMessageDelayed(MSG_STOPSELF_WHEN_DISCONNECT, STOPSELF_WHEN_DISCONNECT_DELAY_TIME);
    }

    @Override
    public void onDestroy() {
        if (batteryChangedReceiver != null) {
            unregisterReceiver(batteryChangedReceiver);
        }
        super.onDestroy();
        if (DEBUG) {
            Log.d(TAG, " service onDestory ");
        }
    }

    private void saveAsync(ChargingDatas chargingDatas, final boolean needStopSelf) {
        final String str = ChargingUtils.toJson(chargingDatas);
        ThreadPoolUtils.getInstance().execute(new Runnable() {

            @Override
            public void run() {
                synchronized (MobileChargingService.this) {
                    try {
                        if (DEBUG) {
                            Log.d(TAG, " saveAsync() needStopSelf=" + needStopSelf);
                            Log.d(TAG, " saveAsync() str=" + str);
                        }
                        ChargingUtils.save(getApplicationContext(), str);
                    } catch (Exception e) {

                    }
                    handler.sendMessage(handler.obtainMessage(MSG_SAVE, needStopSelf));
                }
            }
        });

    }

}
